import pickle
import os
from flask import Flask
from datetime import datetime
import threading
import time
from cachetools import TTLCache


# 初始化Flask应用
app = Flask(__name__)
app.secret_key = 'a_very_secret_key'  # 实际项目中请使用更安全的密钥

# 定义核心目录
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
UPLOAD_FOLDER = os.path.join(BASE_DIR, 'uploads')
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# 定义一个线程安全的 TTL 缓存，最大1000条，600秒过期
data_cache = TTLCache(maxsize=1000, ttl=600)
cache_lock = threading.Lock()

def get_from_cache(key):
    with cache_lock:
        return data_cache.get(key)

def set_to_cache(key, value):
    with cache_lock:
        data_cache[key] = value

def clear_cache():
    with cache_lock:
        data_cache.clear()

# 全局模型缓存
model_cache = {
    'aggregate_model': None,
    'product_models': None,
    'last_loaded': None,
    'loading': False
}

def preload_models():
    """在后台预加载模型"""
    try:
        print("开始预加载商品级别模型...")
        model_cache['loading'] = True

        # 加载聚合模型
        config_path = os.path.join(BASE_DIR, 'config.py')
        if os.path.exists(config_path):
            app.config.from_pyfile(config_path)
            model_path = app.config.get('MODEL_PATH')
            if model_path:
                absolute_model_path = os.path.join(BASE_DIR, model_path)
                if os.path.exists(absolute_model_path):
                    with open(absolute_model_path, 'rb') as f:
                        model_payload = pickle.load(f)
                        # 使用 .get() 提高健壮性，避免因 payload 结构错误导致崩溃
                        agg_model = model_payload.get('model')
                        agg_target = model_payload.get('target', 'y')
                        if agg_model:
                            model_cache['aggregate_model'] = (agg_model, agg_target)
                            print("✓ 聚合模型预加载完成")
                        else:
                            print("✗ 警告: 聚合模型文件中未找到 'model' 键。")

        # 加载商品级别模型
        product_models_path = app.config.get('PRODUCT_MODELS_PATH')
        if product_models_path:
            absolute_path = os.path.join(BASE_DIR, product_models_path)
            if os.path.exists(absolute_path):
                with open(absolute_path, 'rb') as f:
                    product_payload = pickle.load(f)
                    product_models = product_payload.get('models', {})
                    model_cache['product_models'] = product_models
                    print(f"✓ 商品级别模型预加载完成，共 {len(product_models)} 个模型")

        model_cache['loading'] = False
        model_cache['last_loaded'] = datetime.now()
        print("所有模型预加载完成！")

    except Exception as e:
        print(f"模型预加载失败: {e}")
        model_cache['loading'] = False

# --- 加载配置 ---
# 从项目根目录的 config.py 加载配置
# app.root_path 指向 .../spkc_pre/app, os.path.dirname(app.root_path) 指向 .../spkc_pre
config_path = os.path.join(os.path.dirname(app.root_path), 'config.py')
print(f"尝试加载配置文件: {config_path}")

if os.path.exists(config_path):
    print(f"配置文件存在，正在加载...")

    # 手动读取配置文件内容以确保正确加载
    with open(config_path, 'r', encoding='utf-8') as f:
        config_content = f.read()
        print(f"配置文件内容预览: {config_content.strip()}")

    # 使用Flask的配置加载
    app.config.from_pyfile(config_path)

    # 验证配置的模型路径
    model_path = app.config.get('MODEL_PATH')
    print(f"从配置中读取的 MODEL_PATH: {model_path}")

    # 强制设置正确的模型路径（如果配置读取有问题）
    if model_path and 'inventory_prophet_model_accuracy_0.9721' in model_path:
        print("检测到错误的模型路径，强制修正为正确的模型...")
        app.config['MODEL_PATH'] = 'models/prophet_model_accuracy_0.7087_20250620.pkl'
        model_path = app.config['MODEL_PATH']
        print(f"修正后的 MODEL_PATH: {model_path}")

    if model_path:
        absolute_model_path = os.path.join(BASE_DIR, model_path)
        print(f"完整的模型路径: {absolute_model_path}")
        if os.path.exists(absolute_model_path):
            print(f"✓ 配置的模型文件存在: {absolute_model_path}")
        else:
            print(f"✗ 警告: 配置的模型文件不存在: {absolute_model_path}")
    else:
        print("✗ 警告: 配置文件中未设置 MODEL_PATH")
else:
    print(f"✗ 警告: 根目录下未找到 config.py 文件: {config_path}")
    # 设置一个默认值以避免在没有配置文件时崩溃
    app.config.setdefault('MODEL_PATH', None)

# 启动后台模型预加载
print("启动模型预加载线程...")
preload_thread = threading.Thread(target=preload_models, daemon=True)
preload_thread.start()

# 在最后导入路由，避免循环引用
from app import routes  # 导入合并后的主路由
